package com.example.backend.service;

import com.example.backend.domain.entity.TicketStatusTracking;
import com.example.backend.domain.entity.User;
import com.example.backend.domain.enums.TicketStatusTrackingType;
import com.example.backend.dto.TicketStatusTrackingDto;
import com.example.backend.repository.TicketStatusTrackingRepository;
import com.example.backend.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.Optional;

/**
 * 工单状态跟踪服务
 */
@Service
@Transactional
public class TicketStatusTrackingService {
    
    private static final Logger logger = LoggerFactory.getLogger(TicketStatusTrackingService.class);
    
    @Autowired
    private TicketStatusTrackingRepository trackingRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    /**
     * 记录工单状态跟踪
     */
    public TicketStatusTracking recordTracking(Long ticketId, TicketStatusTrackingType trackingType,
                                               String oldValue, String newValue, String fieldName,
                                               String description, Long operatorId, String ipAddress,
                                               String userAgent, Boolean isSystemOperation,
                                               Boolean isVisibleToCustomer) {
        try {
            // 获取操作人信息
            User operator = userRepository.findById(operatorId).orElse(null);
            String operatorName = operator != null ? operator.getFullName() : "未知用户";
            String operatorRole = operator != null ? operator.getRole().name() : "UNKNOWN";
            
            // 创建跟踪记录
            TicketStatusTracking tracking = new TicketStatusTracking();
            tracking.setTicketId(ticketId);
            tracking.setTrackingType(trackingType);
            tracking.setOldValue(oldValue);
            tracking.setNewValue(newValue);
            tracking.setFieldName(fieldName);
            tracking.setDescription(description);
            tracking.setOperatorId(operatorId);
            tracking.setOperatorName(operatorName);
            tracking.setOperatorRole(operatorRole);
            tracking.setIpAddress(ipAddress);
            tracking.setUserAgent(userAgent);
            tracking.setIsSystemOperation(isSystemOperation != null ? isSystemOperation : false);
            tracking.setIsVisibleToCustomer(isVisibleToCustomer != null ? isVisibleToCustomer : true);
            
            TicketStatusTracking saved = trackingRepository.save(tracking);
            logger.info("记录工单状态跟踪成功: ticketId={}, type={}, operator={}", 
                       ticketId, trackingType, operatorName);
            
            return saved;
        } catch (Exception e) {
            logger.error("记录工单状态跟踪失败: ticketId={}, type={}, error={}", 
                        ticketId, trackingType, e.getMessage());
            throw new RuntimeException("记录状态跟踪失败", e);
        }
    }
    
    /**
     * 记录状态变更
     */
    public TicketStatusTracking recordStatusChange(Long ticketId, String oldStatus, String newStatus,
                                                  Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.STATUS_CHANGED, oldStatus, newStatus,
                            "status", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录优先级变更
     */
    public TicketStatusTracking recordPriorityChange(Long ticketId, String oldPriority, String newPriority,
                                                    Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.PRIORITY_CHANGED, oldPriority, newPriority,
                            "priority", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录工单分配
     */
    public TicketStatusTracking recordAssignment(Long ticketId, String oldAssignee, String newAssignee,
                                                Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.ASSIGNED, oldAssignee, newAssignee,
                            "assignedTo", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录工单创建
     */
    public TicketStatusTracking recordCreation(Long ticketId, Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.CREATED, null, "CREATED",
                            "status", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录工单解决
     */
    public TicketStatusTracking recordResolution(Long ticketId, Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.RESOLVED, null, "RESOLVED",
                            "status", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录工单关闭
     */
    public TicketStatusTracking recordClosure(Long ticketId, Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.CLOSED, null, "CLOSED",
                            "status", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录评论添加
     */
    public TicketStatusTracking recordCommentAdded(Long ticketId, Long operatorId, String description, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.COMMENT_ADDED, null, null,
                            "comment", description, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 记录附件添加
     */
    public TicketStatusTracking recordAttachmentAdded(Long ticketId, Long operatorId, String fileName, String ipAddress) {
        return recordTracking(ticketId, TicketStatusTrackingType.ATTACHMENT_ADDED, null, fileName,
                            "attachment", "添加附件: " + fileName, operatorId, ipAddress, null, false, true);
    }
    
    /**
     * 获取工单的状态跟踪记录
     */
    @Transactional(readOnly = true)
    public List<TicketStatusTrackingDto> getTicketTrackingHistory(Long ticketId) {
        List<TicketStatusTracking> trackings = trackingRepository.findByTicketIdOrderByCreatedAtDesc(ticketId);
        return trackings.stream()
                .map(this::convertToDto)
                .toList();
    }
    
    /**
     * 分页获取工单的状态跟踪记录
     */
    @Transactional(readOnly = true)
    public Page<TicketStatusTrackingDto> getTicketTrackingHistory(Long ticketId, Pageable pageable) {
        Page<TicketStatusTracking> trackings = trackingRepository.findByTicketIdOrderByCreatedAtDesc(ticketId, pageable);
        return trackings.map(this::convertToDto);
    }
    
    /**
     * 获取工单的状态变更历史
     */
    @Transactional(readOnly = true)
    public List<TicketStatusTrackingDto> getStatusChangeHistory(Long ticketId) {
        List<TicketStatusTracking> trackings = trackingRepository.findStatusChangeHistoryByTicketId(ticketId);
        return trackings.stream()
                .map(this::convertToDto)
                .toList();
    }
    
    /**
     * 获取工单的分配历史
     */
    @Transactional(readOnly = true)
    public List<TicketStatusTrackingDto> getAssignmentHistory(Long ticketId) {
        List<TicketStatusTracking> trackings = trackingRepository.findAssignmentHistoryByTicketId(ticketId);
        return trackings.stream()
                .map(this::convertToDto)
                .toList();
    }
    
    /**
     * 获取用户可见的跟踪记录
     */
    @Transactional(readOnly = true)
    public List<TicketStatusTrackingDto> getVisibleTrackingHistory(Long ticketId) {
        List<TicketStatusTracking> trackings = trackingRepository.findVisibleToCustomerByTicketId(ticketId);
        return trackings.stream()
                .map(this::convertToDto)
                .toList();
    }
    
    /**
     * 获取工单的最后一次操作
     */
    @Transactional(readOnly = true)
    public Optional<TicketStatusTrackingDto> getLastOperation(Long ticketId) {
        TicketStatusTracking tracking = trackingRepository.findLastOperationByTicketId(ticketId);
        return tracking != null ? Optional.of(convertToDto(tracking)) : Optional.empty();
    }
    
    /**
     * 获取工单的最后一次状态变更
     */
    @Transactional(readOnly = true)
    public Optional<TicketStatusTrackingDto> getLastStatusChange(Long ticketId) {
        TicketStatusTracking tracking = trackingRepository.findLastStatusChangeByTicketId(ticketId);
        return tracking != null ? Optional.of(convertToDto(tracking)) : Optional.empty();
    }
    
    /**
     * 获取操作人的操作记录
     */
    @Transactional(readOnly = true)
    public Page<TicketStatusTrackingDto> getOperatorHistory(Long operatorId, Pageable pageable) {
        Page<TicketStatusTracking> trackings = trackingRepository.findByOperatorIdOrderByCreatedAtDesc(operatorId, pageable);
        return trackings.map(this::convertToDto);
    }
    
    /**
     * 获取时间范围内的跟踪记录
     */
    @Transactional(readOnly = true)
    public Page<TicketStatusTrackingDto> getTrackingHistoryByTimeRange(Instant startTime, Instant endTime, Pageable pageable) {
        Page<TicketStatusTracking> trackings = trackingRepository.findByCreatedAtBetweenOrderByCreatedAtDesc(startTime, endTime, pageable);
        return trackings.map(this::convertToDto);
    }
    
    /**
     * 统计工单的操作次数
     */
    @Transactional(readOnly = true)
    public Long getOperationCount(Long ticketId) {
        return trackingRepository.countByTicketId(ticketId);
    }
    
    /**
     * 统计特定类型的操作次数
     */
    @Transactional(readOnly = true)
    public Long getOperationCountByType(Long ticketId, TicketStatusTrackingType trackingType) {
        return trackingRepository.countByTicketIdAndTrackingType(ticketId, trackingType);
    }
    
    /**
     * 获取操作统计
     */
    @Transactional(readOnly = true)
    public List<Object[]> getOperationStats(Long ticketId) {
        return trackingRepository.getOperationStatsByTicketId(ticketId);
    }
    
    /**
     * 获取操作人统计
     */
    @Transactional(readOnly = true)
    public List<Object[]> getOperatorStats(Long operatorId) {
        return trackingRepository.getOperationStatsByOperatorId(operatorId);
    }
    
    /**
     * 删除工单的所有跟踪记录
     */
    public void deleteTicketTracking(Long ticketId) {
        trackingRepository.deleteByTicketId(ticketId);
        logger.info("删除工单跟踪记录: ticketId={}", ticketId);
    }
    
    /**
     * 清理过期跟踪记录
     */
    public int cleanupExpiredTracking(Instant cutoffTime) {
        int deletedCount = trackingRepository.deleteByCreatedAtBefore(cutoffTime);
        logger.info("清理过期跟踪记录: deletedCount={}, cutoffTime={}", deletedCount, cutoffTime);
        return deletedCount;
    }
    
    /**
     * 转换为DTO
     */
    private TicketStatusTrackingDto convertToDto(TicketStatusTracking tracking) {
        return new TicketStatusTrackingDto(
                tracking.getId(),
                tracking.getTicketId(),
                tracking.getTrackingType(),
                tracking.getOldValue(),
                tracking.getNewValue(),
                tracking.getFieldName(),
                tracking.getDescription(),
                tracking.getOperatorId(),
                tracking.getOperatorName(),
                tracking.getOperatorRole(),
                tracking.getIsSystemOperation(),
                tracking.getIsVisibleToCustomer(),
                tracking.getCreatedAt()
        );
    }
}

